﻿using System;
using System.Collections;

namespace GameBasic
{
    public static class ExtEnum
    {
        public static bool Any<T>(this T value, T flags) where T : unmanaged, Enum
        {
            long v0 = 0;
            long v1 = 0;
            unsafe
            {
                *(T*)&v0 = value;
                *(T*)&v1 = flags;
            }
            return (v0 & v1) != 0;
        }

        public static bool Any<T>(this T value, T flags, T ignores) where T : unmanaged, Enum
        {
            long v0 = 0;
            long v1 = 0;
            long vIgnore = 0;
            unsafe
            {
                *(T*)&v0 = value;
                *(T*)&v1 = flags;
                *(T*)&vIgnore = ignores;
            }
            v1 &= ~vIgnore;
            return (v0 & v1) != 0;
        }

        public static bool All<T>(this T value, T flags) where T : unmanaged, Enum
        {
            long v0 = 0;
            long v1 = 0;
            unsafe
            {
                *(T*)&v0 = value;
                *(T*)&v1 = flags;
            }
            return (v0 & v1) == v1;
        }

        public static bool All<T>(this T value, T flags, T ignores) where T : unmanaged, Enum
        {
            long v0 = 0;
            long v1 = 0;
            long vIgnore = 0;
            unsafe
            {
                *(T*)&v0 = value;
                *(T*)&v1 = flags;
                *(T*)&vIgnore = ignores;
            }

            v1 &= ~vIgnore;
            return (v0 & v1) == v1;
        }

        public static T Remove<T>(ref this T value, T flags) where T : unmanaged, Enum
        {
            long v0 = 0;
            long v1 = 0;

            unsafe
            {
                T* p0 = (T*)&v0;
                T* p1 = (T*)&v1;
                *p0 = value;
                *p1 = flags;
                v0 &= ~v1;

                return *p0;
            }
        }

        public static T Set<T>(ref this T value, T flags, bool on) where T : unmanaged, Enum
        {
            long v0 = 0;
            long v1 = 0;

            unsafe
            {
                T* p0 = (T*)&v0;
                T* p1 = (T*)&v1;
                *p0 = value;
                *p1 = flags;

                v0 &= ~v1;
                if (on)
                    v0 |= v1;

                return *p0;
            }
        }

        public static bool Compare<T>(T t0, T t1) where T : unmanaged, Enum
        {
            long v0 = 0;
            long v1 = 0;
            unsafe
            {
                *(T*)&v0 = t0;
                *(T*)&v1 = t1;
            }
            return v0 == v1;
        }

        public static bool Compare32<T>(T t0, T t1) where T : unmanaged, Enum
        {
            int v0 = 0;
            int v1 = 0;
            unsafe
            {
                *(T*)&v0 = t0;
                *(T*)&v1 = t1;
            }
            return v0 == v1;
        }
    }
}